﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;
using Core.Model;
using System.Data.Objects;
using Core.UnitOfWork;
using Core.Repository;
using System.Data.Entity;
using System.Transactions;

namespace Core.Service
{
    public class Service<TEntity, TContext> : IService<TEntity>
        where TEntity : class,IKey<int>
        where TContext : DbContext, new()
    {

        #region IService 成员

        public virtual TEntity Get(object id)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                //service 作为外部调用的接口，即所有业务在这一层实现，所以返回的结果不再需要延迟加载等功能
                unitOfWork.LazyLoadingEnabled = false;
                unitOfWork.ProxyCreationEnabled = false;
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                return repository.Get(id);
            }
        }

        public virtual void Add(TEntity item)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                repository.Add(item);
                unitOfWork.Save();
            }
        }

        public virtual void Update(TEntity item)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                repository.Update(item);
                unitOfWork.Save();
            }
        }

        public virtual void Delete(TEntity item)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                repository.Delete(item);
                unitOfWork.Save();
            }
        }

        public virtual IList<TEntity> Find(Func<TEntity, bool> expression)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                //service 作为外部调用的接口，即所有业务在这一层实现，所以返回的结果不再需要延迟加载等功能
                unitOfWork.LazyLoadingEnabled = false;
                unitOfWork.ProxyCreationEnabled = false;
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                return repository.Find(expression);
            }
        }

        public virtual IList<TEntity> Find<Tkey>(Func<TEntity, bool> expression,
            Func<TEntity, Tkey>[] orderby, bool[] isDescending, int pageIndex, int pageCount)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                //service 作为外部调用的接口，即所有业务在这一层实现，所以返回的结果不再需要延迟加载等功能
                unitOfWork.LazyLoadingEnabled = false;
                unitOfWork.ProxyCreationEnabled = false;
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                return repository.Find(expression, orderby, isDescending, pageIndex, pageCount);
            }
        }

        public virtual IList<TEntity> Find<Tkey>(Func<TEntity, bool> expression,
            Func<TEntity, Tkey>[] orderby, bool[] isDescending, int pageIndex, int pageCount, out int pages)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                //service 作为外部调用的接口，即所有业务在这一层实现，所以返回的结果不再需要延迟加载等功能
                unitOfWork.LazyLoadingEnabled = false;
                unitOfWork.ProxyCreationEnabled = false;
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                return repository.Find(expression, orderby, isDescending, pageIndex, pageCount, out pages);
            }
        }

        public virtual IList<TEntity> Find<Tkey>(Func<TEntity, bool> expression,
          Func<TEntity, Tkey>[] orderby, bool[] isDescending, int pageIndex, int pageCount, out int pages, out int records)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);
                //service 作为外部调用的接口，即所有业务在这一层实现，所以返回的结果不再需要延迟加载等功能
                unitOfWork.LazyLoadingEnabled = false;
                unitOfWork.ProxyCreationEnabled = false;
                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);
                return repository.Find(expression, orderby, isDescending, pageIndex, pageCount, out pages, out records);
            }
        }

        public virtual void InsertOrUpdate(TEntity obj)
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);

                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);

                if (repository.Get(obj.Id) == null)
                {
                    repository.Add(obj);
                }
                else
                {
                    repository.Update(obj);
                }

                unitOfWork.Save();

            }
        }

        public virtual void InsertOrUpdate(List<TEntity> list)
        {
            using (TContext context = new TContext())
            {
                using (TransactionScope transaction = new TransactionScope())
                {
                    IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);

                    IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);

                    foreach (var i in list)
                    {
                        if (repository.Get(i.Id) == null)
                        {
                            repository.Add(i);
                        }
                        else
                        {
                            repository.Update(i);
                        }
                        unitOfWork.Save();
                    }

                    
                    transaction.Complete();

                }
            }
        }

        public virtual IList<TEntity> FindAll()
        {
            using (TContext context = new TContext())
            {
                IUnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(context);

                IRepository<TEntity> repository = new Repository<TEntity>(unitOfWork);

                return repository.FindAll();

            }
        }

        #endregion
    }
}
